package com.example.util;

import com.alibaba.fastjson.JSONObject;
import com.example.annotation.ConvertEntity;
import com.example.annotation.ConvertField;
import com.example.entity.ElastStudent;
import com.example.entity.Entity;
import com.example.entity.EntityDto;
//import org.springframework.beans.BeanUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.map.HashedMap;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


public class MyBeatUtil {

    public static  Map<String,Object> entityToMap(Object o)
    {
//        String jsonStr = JSONObject.toJSONString(o);
//
//        JSONObject jsonObject= JSONObject.parseObject(jsonStr);
        //JSONOBJECT也是map的子类，可以通过ali的包转成字符串，在转成jsonobject

        /*
        们可以启用java.security.manager来判断程序是否具有调用setAccessible()的权限。
        默认情况下，内核API和扩展目录的代码具有该权限，
        而类路径或通过URLClassLoader加载的应用程序不拥有此权限。
        所以项目代码慎用，万一不能编译就gg，还是多用get的方法比较好，用这种
        TestString firstLetter = fieldName.substring(0, 1).toUpperCase();
               TestString getMethodName = "get" + firstLetter + fieldName.substring(1);
               或者后去所有方法，判断是否以get开头等
         */
        Map<String,Object> hashmap = new HashMap();
        Class cla = o.getClass();
        Field[] fileds = cla.getDeclaredFields();
        for (Field field : fileds)
        {
            field.setAccessible(true);
            try {
                hashmap.put(field.getName(),field.get(o));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            //field.setAccessible(false);看main函数里面还能不能访问属性，如果能，必须set false,结果还是不能访问哈
        }
        return hashmap;
    }

    public static <T> T convertEntityByMethod(Object object, Class<T> tClass)
    {
        Class<?> class1 = object.getClass();
        ConvertEntity entity  =class1.getAnnotation(ConvertEntity.class);
        if (null!=entity&& entity.value().equals(tClass))
        {
            Method[] methods = class1.getMethods();
            HashMap<String,Object> hashMap = new HashMap<>();
            for (Method method : methods)
            {
                ConvertField field = method.getAnnotation(ConvertField.class);
                if(null!=field)
                    try {
                        Object value = method.invoke(object);
                        if(value!=null){
                            hashMap.put(field.value(), value);
                        }
                    } catch (Exception e) {
                        //log.info("执行此convertfield{0}方法出现异常",field.value());
                        System.out.println("执行此convertfield{0}方法出现异常");
                        e.printStackTrace();
                    }
            }
                try {
                    T t = tClass.newInstance();
                    BeanUtils.populate(t,hashMap);
                    return   t;
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("反射失败");
                    return  null;
                }
        }
        return  null;
    }
    public  static  <T> T convertEntityByField(Object object,Class<T> tClass)
    {
        Class<?> class1 = object.getClass();
        ConvertEntity entity  =class1.getAnnotation(ConvertEntity.class);
        if (null!=entity&& entity.value().equals(tClass))
        {
            //Method[] methods = class1.getMethods();
            Field[] fields = class1.getDeclaredFields();//暂时可以不包括父类，可以不用delcared，这样就能包括弗雷
            HashMap<String,Object> hashMap = new HashMap<>();
            for (Field field : fields)
            {
                ConvertField field1 = field.getAnnotation(ConvertField.class);
                if(null!=field1)
                    try {
                    field.setAccessible(true);
                    if (null!=field.get(object))
                        hashMap.put(field1.value(),field.get(object));
                    } catch (Exception e) {
                        //log.info("执行此convertfield{0}方法出现异常",field.value());
                        System.out.println("执行此convertfield{0}方法出现异常");
                        e.printStackTrace();
                    }
            }
                try {
                    T t = tClass.newInstance();
                    BeanUtils.populate(t,hashMap);
                    return   t;
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("反射失败");
                    return  null;
                }
        }
        return  null;
    }




    public static void main(String[] args) {
        //测试下tohashmap
        ElastStudent student = new ElastStudent();
        student.setAddress("1234");
        //student.setBirthday();
        System.out.println(entityToMap(student));

//        //copyProerties 方法确实好，只要属性名称相同就能转化，但是属性里面有本身就不行了，需要自己手动在copy一次
//        Entity another = new Entity("1",1,null,1,true,"ano");
//        Entity entity = new Entity();
//        entity.setName("inner");
//        another.setMyself(entity);
//        System.out.println(another);
////
//        EntityDto dto = new EntityDto();
//        EntityDto anodto = new EntityDto();
//        //anodto.setName("123");
////        BeanUtils.copyProperties(another,dto);
//        //dto=  convertEntityByMethod(another,EntityDto.class);
//        anodto=  convertEntityByField(another,EntityDto.class);
//
//        System.out.println(dto);
//        System.out.println(anodto);
////
//        if (null!=another.getMyself())
//        {
//            EntityDto dto1 = new EntityDto();
//            //BeanUtils.copyProperties(another.getMyself(),dto1);
//            //dto1 = convertEntityByMethod(another.getMyself(),EntityDto.class);
//            dto1=  convertEntityByField(another.getMyself(),EntityDto.class);
//            dto.setMyself(dto1);
//        }
//        //dto.setMyself(anodto);
//        System.out.println(dto);
//
        }
    //使用递归，来判断属性自身中包含自己还需不需要转化
}
